@file:Suppress("SpellCheckingInspection")

package han.cirno.corrupt.components.school.impl.fafu

import han.cirno.corrupt.util.RegexUtil
import han.cirno.corrupt.util.getBodyStringAndClose
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.io.Serializable

class FafuLibClient {
    companion object {
        val instance: FafuLibClient = FafuLibClient()
    }

    private val okHttpClient = OkHttpClient()
    fun requestSearch(keyword: String, page: Int):Result<SearchResults> {
        try {
            val request =
                Request.Builder().url(FafuLibConst.getSearchPageAddress(keyword, page)).build()
            val result =okHttpClient.newCall(request).execute().getBodyStringAndClose()!!
            val document = Jsoup.parse(result)
            val results = parsePage(document)
            val pageNumsElement = document.getElementById("pagenum")
            var pages=0
            if(pageNumsElement!=null&&pageNumsElement.childrenSize()!=0){
                val child = pageNumsElement.child(0)
                pages=child.text().split("/")[1].toInt()
            }
            return Result.success(SearchResults(results,pages))
        }catch (e:Exception){
            return Result.failure(e)
        }
    }

    fun requestDetail(param:String):Result<BookDetail>{
        try{
            val request= Request.Builder()
                .url(FafuLibConst.getDetailAddress())
                .post(FormBody.Builder()
                    .add("xc","3")
                    .add("detailParam",param).build())
                .build()
            val result = okHttpClient.newCall(request).execute().getBodyStringAndClose()!!
            val document = Jsoup.parse(result)
            return Result.success(parseDetailPage(document))
        }catch (e:Exception){
            return Result.failure(e)
        }
    }

    private fun parseDetailPage(document: Document): BookDetail {
        val catalogHtml = document.getElementsByClass("catalog").html()
        val description=RegexUtil.matchFirst("(?<=\\<p\\>提要文摘附注：).*?(?=</p>)",catalogHtml)?:""
        val isbnAndPrice=RegexUtil.matchFirst("(?<=\\<p\\>ISBN及定价：).*?(?=</p>)",catalogHtml)?:""
        val payload=RegexUtil.matchFirst("(?<=\\<p\\>载体形态项：).*?(?=</p>)",catalogHtml)?:""
        val theme=RegexUtil.matchFirst("(?<=\\<p\\>学科主题：).*?(?=</p>)",catalogHtml)?:""
        val placeElements = document.getElementsByClass("tablelib")
        val bookPlaces=ArrayList<BookPlace>()
        placeElements.forEach {
            val tbody = it.getElementsByTag("tbody")
            val html = tbody.html().replace("\n","").replace("\r","")
            val serial=RegexUtil.matchFirst("(?<=\\<th\\>条码号\\</th\\> \\<td\\>).*?(?=</td>)",html)?:""
            val place=RegexUtil.matchFirst("(?<=\\<th\\>馆藏地\\</th\\> \\<td\\>).*?(?=</td>)",html)?:""
            val status=RegexUtil.matchFirst("(?<=\\<th\\>书刊状态\\</th\\> \\<td\\>).*?(?=</td>)",html)?:""
            val code=RegexUtil.matchFirst("(?<=\\<th\\>索书号\\</th\\> \\<td\\>).*?(?=</td>)",html)?:""
            bookPlaces.add(BookPlace(serial, place, status, code))
        }
        return BookDetail(description, isbnAndPrice, payload, theme, bookPlaces)
    }

    private fun parsePage(document:Document):MutableList<SearchResult>{
        val divList = document.getElementsByClass("list")
        val tableElement = divList.elementAt(0).child(0)
        val list=ArrayList<SearchResult>()
        tableElement.children().forEach {
            val requestParam = it.getElementsByAttributeValue("name", "detailParam").attr("value")
            val name =
                it.getElementsByClass("title").text().run { substring(indexOf(' ') + 1) }
            val details = it.getElementsByClass("detail").html()
            val author=RegexUtil.matchFirst("(?<=\\<p\\>作者：).*?(?=</p>)",details)?:""
            val callNumber=RegexUtil.matchFirst("(?<=\\<p\\>索书号：).*?(?=</p>)",details)?:""
            val type=RegexUtil.matchFirst("(?<=\\<p\\>流通类型：).*?(?=</p>)",details)?:""
            val availability=RegexUtil.matchFirst("(?<=\\<p\\>可借/总藏：).*?(?=</p>)",details)?:""
            val press=RegexUtil.matchFirst("(?<=\\<p\\>出版： ).*?(?=</p>)",details)?:""
            list.add(SearchResult(name,author,callNumber,type,availability,press,requestParam))
        }
        return list
    }

    data class BookDetail(
        val description:String,
        val isbnAndPrice:String,
        val payload:String,
        val theme:String,
        val bookPlaces:MutableList<BookPlace>):Serializable
    data class BookPlace(
        val serial:String,
        val place:String,
        val status:String,
        val code:String):Serializable
    data class SearchResults(
        val results:MutableList<SearchResult>,
        val totalPages:Int)
    data class SearchResult(
        val name:String,
        val author: String,
        val callNumber: String,
        val type: String,
        val availability: String,
        val press: String,
        val requestParam: String)
}